package com.kelvin.backend.redis.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * <p>Title: RedisService</p>
 * <p>Description: </p>
 *
 * @author Kelvin.Chen
 * @datetime 2021/7/12 10:25
 */
@Service("redisService")
public class RedisService implements IRedisService {

    private static final Logger log = LoggerFactory.getLogger(RedisService.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public boolean set(String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            log.error("插入出现异常 -> ", e);
        }
        return result;
    }

    @Override
    public boolean set(String key, Object value, Long expireTime) {
        return set(key, value, expireTime, TimeUnit.SECONDS);
    }

    @Override
    public boolean set(String key, Object value, Long expireTime, TimeUnit timeUnit) {
        set(key, value);
        return redisTemplate.expire(key, expireTime, timeUnit);
    }

    @Override
    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public boolean remove(String key) {
        return redisTemplate.delete(key);
    }

    @Override
    public void remove(String... keys) {
        Arrays.stream(keys).forEach(key -> remove(key));
    }

    @Override
    public void removePattern(String pattern) {
        Set<Serializable> keys = redisTemplate.keys(pattern);
        if (!keys.isEmpty()) {
            redisTemplate.delete(keys);
        }
    }

    @Override
    public Object get(String key) {
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        return operations.get(key);
    }

    @Override
    public void hPut(String key, Object hashKey, Object value) {
        HashOperations<String, Object, Object> operations = redisTemplate.opsForHash();
        operations.put(key, hashKey, value);
    }

    @Override
    public Object hGet(String key, Object hashKey) {
        HashOperations<String, Object, Object> operations = redisTemplate.opsForHash();
        return operations.get(key, hashKey);
    }

    @Override
    public void lPush(String key, Object value) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        operations.leftPush(key, value);
    }

    @Override
    public void rPush(String key, Object value) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        operations.rightPush(key, value);
    }

    @Override
    public void lPop(String key) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        operations.leftPop(key);
    }

    @Override
    public void rPop(String key) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        operations.rightPop(key);
    }

    @Override
    public List<Object> lRange(String key, long start, long end) {
        ListOperations<String, Object> operations = redisTemplate.opsForList();
        return operations.range(key, start, end);
    }

    @Override
    public void sAdd(String key, Object value) {
        SetOperations<String, Object> operations = redisTemplate.opsForSet();
        operations.add(key, value);
    }

    @Override
    public Set<Object> setMembers(String key) {
        SetOperations<String, Object> operations = redisTemplate.opsForSet();
        return operations.members(key);
    }

    @Override
    public void zAdd(String key, Object value, double score) {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        operations.add(key, value, score);
    }

    @Override
    public void zIncrementScore(String key, Object value, double score) {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        operations.incrementScore(key, value, score);
    }

    @Override
    public Double zScore(String key, Object value) {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        return operations.score(key, value);
    }

    @Override
    public Set<Object> rangeScore(String key, double score1, double score2) {
        ZSetOperations<String, Object> operations = redisTemplate.opsForZSet();
        return operations.rangeByScore(key, score1, score2);
    }

    @Override
    public boolean setIfAbsent(String key, Object value, long secod) {
        return redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofSeconds(secod));
    }
}
